AWS Security Hub の検出結果を自動で「通知済み」にする
はじめに
Security Hub 検知の通知(or 自動起票)の悩み
AWS Security Hub にセキュリティイベントを集約して、 アクションのトリガーを作成するケースは多いです。 「メール・Slackへ通知」するケースもありますし、 「特定タスク管理ツールへ自動起票する」仕組みを作ることもあります。 例えば以下のブログでは、「Security Hub検知をBacklogへ自動起票する仕組み」を作っています。
こういった通知(or 自動起票)の仕組みを作ったときに出てくる悩みとして、 「定期的に同じ通知が飛んでくる」があります。 これはSecurity Hubの定期的なチェックのためです。 チェックを行うたびに検出結果が更新されて、それが検知されます。
最初のチェックの後、各コントロールのスケジュールは、定期的に実行されるか、変更によってトリガーされます。
- 定期的なチェックは、最後の実行から 12 時間以内に自動的に実行 されます。周期を変更することはできません。
- 変更によってトリガーされるチェックは、関連付けられたリソースの状態が変更されたときに実行されます。リソースの状態が変わらない場合でも、変更によってトリガーされるチェックの更新時刻は 18 時間ごとに更新 されます。これは、コントロールがまだ有効であることを知るのに便利です。
ワークフローステータスの活用
同じ通知が飛ばないようにするためには ワークフローのステータス を活用できます。 これは各検出結果に設定できるステータスです。 NEW
(新規), NOTIFIED
(通知済み) SUPPRESSED
(抑制済み), RESOLVED
(解決済み) の4値のいずれかを設定できます。
例えば通知された検出結果を NOTIFIED
(通知済み)に変更したとします。 EventBridgeルールで「 NOTIFIED
にしたものは通知対象外にする」フィルタ(参考: 例3)を設定することで、 その通知( NOTIFIED
にしたもの ) は再度通知されなくなります。
『「通知済み」にする』を自動化する
今回は「通知された検出結果を NOTIFIED
(通知済み)に変更する」部分を 自動化します。Step Functionsを使って簡単に実装できます。
作ったもの
以下リソース(EventBridge, Step Functions)を作りました。
EventBridgeルール(フィルタ)
EventBridgeルールのフィルタパターンは以下のようにしました。 CRITICALの検出結果で失敗しているコントロールを検知します。
{ "detail": { "findings": { "Compliance": { "Status": [{ "anything-but": "PASSED" }] }, "ProductName": ["Security Hub"], "RecordState": ["ACTIVE"], "Severity": { "Label": ["CRITICAL"] }, "Workflow": { "Status": ["NEW"] } } }, "detail-type": ["Security Hub Findings - Imported"], "source": ["aws.securityhub"] }
【注意】ワークフローのステータス(Workflow.Status)のフィルタを必ず付与してください。 このフィルタがないと以下のようなループが発生します。
- 検出結果がEventBridge で検知、Step Functionsステートマシンが起動される
- 検出結果を「通知済み」に更新する
- 更新した検出結果が EventBridge で検知、Step Functionsステートマシンが起動される
- 検出結果を「通知済み」に更新する
- 更新した検出結果が EventBridge で検知、Step Functionsステートマシンが起動される
- 検出結果を「通知済み」に更新する
- (以下無限ループ)
EventBridgeルール(ターゲット)
EventBridgeルールのターゲット設定は以下のとおり。Step Functionsステートマシンを指定します。
ターゲットにステートマシンを指定するときに、IAMロールが必要になります。 キャプチャの test-security-events-role
の部分です。 IAMロールのポリシーは以下のように 「ステートマシンの起動」のみを許可しています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "states:StartExecution", "Resource": "${aws_sfn_state_machine.this.arn}" } ] }
Step Functionsステートマシン
ステートマシンの構成は以下のとおり。見てのとおりシンプルです。
BatchUpdateFindings APIを実行しています。 入力パラメータは以下のとおり。
{ "FindingIdentifiers": [ { "Id.$": "$.detail.findings[0].Id", "ProductArn.$": "$.detail.findings[0].ProductArn" } ], "Workflow": { "Status": "NOTIFIED" } }
(追記) ステートマシンのIAMロールには以下のように、 securityhub:BatchUpdateFindings
アクションを許可する必要があります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "securityhub:BatchUpdateFindings" ], "Resource": "*" } ] }
確認
「SSHを全開放」なEC2セキュリティグループを作成してみます。 これは基礎セキュリティのベストプラクティスの [EC2.19] Security groups should not allow unrestricted access to ports with high risk
にて非準拠になります。
しばらくして確認すると、すでに NOTIFIED
になっていました。
ステートマシンの実行ログも確認しました。問題ないですね。
おわりに
AWS Security Hub の検出結果を自動で「通知済み」にする仕組みを作ってみました。
実際にはこれ単体で使うことは無いです。 以下のような組み合わせで活用する想定です。
- このステートマシンに「通知(or 自動起票)の処理」を追加する
- EventBridgeルールのターゲットに「通知(or 自動起票)の処理」を追加する 等
以上、参考になれば幸いです。
参考
- EventBridge event formats for Security Hub - AWS Security Hub
- BatchUpdateFindings - AWS Security Hub
- EventBridge API Destinationsを使ってSecurity Hub検知をBacklogに自動起票してみた | DevelopersIO
- AWSアカウント名を含めたセキュリティ通知を作ってみる(AWS Organizations) | DevelopersIO
追記情報
【2023-09-15】 ループがそもそも出ないように対策した Step Functions ステートマシン
【注意】ワークフローのステータス(Workflow.Status)のフィルタを必ず付与してください。 このフィルタがないと以下のようなループが発生します。
上記のループ対策版 Step Functions ステートマシンを以下に記載します。
{ "Comment": "Security Hub finding handler", "StartAt": "Choice by workflow status", "States": { "Choice by workflow status": { "Type": "Choice", "Choices": [ { "Not": { "Variable": "$.detail.findings[0].Workflow.Status", "StringEquals": "NOTIFIED" }, "Comment": "not NOTIFIED", "Next": "Set a finding as NOTIFIED" } ], "Default": "End" }, "End": { "Type": "Pass", "End": true }, "Set a finding as NOTIFIED": { "Type": "Task", "Parameters": { "FindingIdentifiers": [ { "Id.$": "$.detail.findings[0].Id", "ProductArn.$": "$.detail.findings[0].ProductArn" } ], "Workflow": { "Status": "NOTIFIED" } }, "Resource": "arn:aws:states:::aws-sdk:securityhub:batchUpdateFindings", "Next": "End" } } }